const kInitImageProducerReq       = 0;
const kUninitImageProducerReq     = 1;
const kFeedFrameDataReq          = 2;


//ImageProducer response.
const kInitImageProducerRsp       = 0;
const kUninitImageProducerRsp     = 1;
const kVideoFrame                 = 2;


self.Module = {
    onRuntimeInitialized: function () {
        onWasmLoaded();
    }
};


self.importScripts('imagePro.js');

function ImageProducer() {
    this.wasmLoaded = false;
    this._dataBuffer = null;
    this._srcImage = null;
    this._dataSize = 30*36;
    this._iamgeSize = 0;
    this._id = 0;
    this._proTimer= null;
    this._frameDataArr = [];
    this._initParam = null;
}

ImageProducer.prototype.initImageProducer = function (w, h) {
    if(!this.wasmLoaded) return;
    var paramCount = 1, paramSize = 4, id = 0;
    var paramByteBuffer = Module._malloc(paramCount * paramSize);
    var ret = Module._InitImageAdd(paramByteBuffer,w, h, this.videoCallback);
    if (ret == 0) {
        var paramIntBuff    = paramByteBuffer >> 2;
        var paramArray      = Module.HEAP32.subarray(paramIntBuff, paramIntBuff + paramCount);
        this._id = paramArray[0];
        this._iamgeSize = w*h;
        //this._dataSize = 30*60;
        this._dataBuffer = Module._malloc(this._dataSize);
        this._proTimer = setInterval( this.productOneImage.bind(this),40)

    }
    Module._free(paramByteBuffer);

    var objData = {
        t: kInitImageProducerRsp,
        e: ret
    };
    self.postMessage(objData);
};

ImageProducer.prototype.uninitImageProducer = function () {
    if(!this.wasmLoaded) return;
    if(this._id) {
        Module._InitImageAdd(this._id);
    }
    if(this._dataBuffer) {
        Module._free(this._dataBuffer);
        this._dataBuffer = null;
    }
    if(this._srcImage){
        Module._free(this._srcImage);
        this._srcImage = null;
    }
    this._frameDataArr = [];
    if(this._proTimer) {
        clearInterval(this._proTimer);
        this._proTimer = null;
    }
    this._initParam = null;
    var objData = {
        t: kUninitImageProducerRsp,
        e: 0
    };
    self.postMessage(objData);
};

ImageProducer.prototype.imageProducerByFrame = function (data, type, pts, srcimg, width, height) {
    if(!this._id || data.length != this._dataSize) {
        return -1;
    }
    if(type && (!srcimg || (srcimg.length != this._iamgeSize*4 && srcimg.length != this._iamgeSize*3 && srcimg.length != this._iamgeSize*3/2) )) {
        return -1;
    }
    //var typedArray = data;//new Uint8Array(data);
    Module.HEAPU8.set(data, this._dataBuffer);
    if(type && srcimg) {
        if(!this._srcImage) {
            this._srcImage = Module._malloc(this._iamgeSize*4);
        }
        Module.HEAPU8.set(srcimg, this._srcImage);
    }
    var ret  = Module._GetImageAdd(this._id, this._dataBuffer, data.length, type, pts, this._srcImage, srcimg?srcimg.length:0);
    if(ret != 0) {
        console.log("_GetImageAdd = ", ret);
    }
};

ImageProducer.prototype.productOneImage = function(){
    var frame = this._frameDataArr.shift();
    if(frame){
        this.imageProducerByFrame(frame.d, frame.c, frame.s, frame.i, frame.w, frame.h);
    }
}




ImageProducer.prototype.cacheAndProReq = function(req) {
    switch (req.t) {
        case kInitImageProducerReq:
            this._initParam = {w: req.w, h: req.h}
            this.initImageProducer(req.w, req.h);
            break;
        case kFeedFrameDataReq:
            if(this._frameDataArr.length < 3){
                this._frameDataArr.push(req);
            }
            break;
        case kUninitImageProducerReq:
            this.uninitImageProducer();
            break;
        default:
          //  this.logger.logError("Unsupport messsage " + req.t);
    }
};


ImageProducer.prototype.onWasmLoaded = function () {
    this.wasmLoaded = true;
    var _this = this;

    this.videoCallback = Module.addFunction(function (y, ysize, u, usize, v, vsize, width, height, timestamp, type) {
        //console.log("videoCallback ",width, height, timestamp)
        var outArray = Module.HEAPU8.subarray(y, y+ysize);
        var ydata = new Uint8Array(outArray);
        outArray = Module.HEAPU8.subarray(u, u+usize);
        var udata = new Uint8Array(outArray);
        outArray = Module.HEAPU8.subarray(v, v+vsize);
        var vdata = new Uint8Array(outArray);
        var objData = {
            t: kVideoFrame,
            w: width,
            h: height,
            s: timestamp,
            y: ydata,
            u: udata,
            v: vdata,
            c: type
        };
        self.postMessage(objData, [objData.y.buffer],[objData.u.buffer], [objData.v.buffer]);
    });

    if(this._initParam) {
        this.initImageProducer(this._initParam.w, this._initParam.h);
    }
};

self.ImageProducer = new ImageProducer;

self.onmessage = function (evt) {
    if (!self.ImageProducer) {
        console.log("[ER] ImageProducer not initialized!");
        return;
    }

    var req = evt.data;
    self.ImageProducer.cacheAndProReq(req);
};

function onWasmLoaded() {
    if (self.ImageProducer) {
        self.ImageProducer.onWasmLoaded();
    } else {
        console.log("[ER] No ImageProducer!");
    }
}
